package com.sdyc.ndmp.cls.engine;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.sdyc.ndmp.cls.dtd.KeywordCondition;
import com.sdyc.ndmp.cls.model.MomW;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;
import java.util.Map;
import java.util.Set;

public class PrimeFilter implements Filter {

    private static Log LOG = LogFactory.getLog(PrimeFilter.class);

    /**
     * 匹配条件
     */
    private KeywordCondition condition;

    /**
     * 过滤条件
     */
    protected final List<Filter> filters;

    public PrimeFilter(KeywordCondition condition) {
        this.condition = condition;

        MomW momW = condition.getMomW();

        Match matchType = Match.valueOf(momW.getContains());
        Set<String> words = momW.getWords();
        //LOG.info("核心词匹配>>>>>> "+momW);
        //TODO 这里进行编译, 把condition中的主条件提取出来, 编译为 Filter
        filters = ImmutableList.<Filter>of(new PrimeKeywordFilter(matchType, words));
    }

    public PrimeFilter(Match matchType , Set<String> words) {
        //TODO 这里进行编译, 把condition中的主条件提取出来, 编译为 Filter
        filters = ImmutableList.<Filter>of(new PrimeKeywordFilter(matchType, words));
    }

    @Override
    public boolean accept(DataKeywords post) {
        //主条件有任何一个不通过, 则返回 false
        for (Filter filter : filters) {
            if(!filter.accept(post)) {
                return false;
            }
        }

        //全部都通过了, 返回 true
        return true;
    }


    /**
     *
     * 返回主条件词, 以及需要把主条件词按照 MATCH_TYPE 组合成词距 Map
     *
     * @return 返回主条件词距
     */
    public Map<Match, Set<String>> primeKeywords() {
        //从 Condition 中提取匹配次
        //以上所有条件下的 Keyword

        MomW momW = condition.getMomW();

        Match matchType = Match.valueOf(momW.getContains());

        //全部不包含, 不能添加附加关键字
        if(matchType == Match.MATCH_NOT) {
            return ImmutableMap.<Match, Set<String>>of();
        }

        Map<Match, Set<String>> allWords = ImmutableMap.<Match, Set<String>>of(
                matchType, momW.getWords()
        );
        return allWords;
    }
}

/**
 * 主条件词 Filter
 *
 */
class PrimeKeywordFilter implements Filter {

    /**
     * 匹配模式, 默认为全匹配
     */
    protected Match matchType = Match.MATCH_ALL;

    /**
     * 需要匹配的关键词
     */
    protected Set<String> words;

    /**
     * 关键词构造方法
     * @param words 匹配词
     */
    public PrimeKeywordFilter(Set<String> words) {
        this.words = words;
    }

    public PrimeKeywordFilter(Match matchType, Set<String> words) {
        this.matchType = matchType;
        this.words = words;
    }

    @Override
    public boolean accept(DataKeywords post) {
        String text = post.getText();
        if(StringUtils.isEmpty(text)){
            return false;
        }
        //匹配过滤
        switch (matchType) {
            case MATCH_ANY:
                //包含任意, 返回 true
                for (String word : words) {
                   //不等于 null, 则包含, 任意包含都要返回 true
                   if(post.getKeywordRange().get(word) != null || text.toLowerCase().contains(word.toLowerCase())) {
                       return true;
                   }
                }
                return false;
            case MATCH_NOT:
                //全部不包含, 返回 true
                for (String word : words) {
                    //不等于 null, 则包含, 任意包含都要返回 false
                    if(post.getKeywordRange().get(word) != null || text.toLowerCase().contains(word.toLowerCase())) {
                        return false;
                    }
                }
                return true;
            default:
                //全部包含, 返回 true
                for (String word : words) {
                    //不等于 null, 则包含, 全部包含才返回 true, 不包含任意一个, 都返回 false
                    if(post.getKeywordRange().get(word) == null || !text.toLowerCase().contains(word.toLowerCase())) {
                        return false;
                    }
                }
                return true;
        }
    }
}

